import asyncio
import time

from nicegui import ui
from services.control.api import ControlApi
from services.automatic_control.api import AutomaticControlApi


def create_card(name: str, color: str):
    index = int(name[2:]) - 1 + (2 if 'SM' in name else 0)

    card = ui.card()
    card.style('background-color: #FCFCFC')

    def get_correct_numbers():
        try:
            ac = AutomaticControlApi()
            return ac.get_output_power_correct_number(index),\
                ac.get_additional_output_power_correct_number(index),\
                ac.get_current_output_power(index)

        except Exception:
            return -1.0, -1.0, -1.0

    with card:
        lable = ui.label(name)
        lable.style(f'margin: 0 auto; color: {color}; font-size: large; font-weight: 900')

        cn, acn, cop = get_correct_numbers()

        current_output_power = ui.label(f'current output power: {cop:.3f}')
        current_output_power.style('font-size: medium;')

        correct_number = ui.number(label='correct number', value=cn, format='%.1f')
        correct_number.style('font-size: medium;')

        additional_correct_number = ui.number(label='additional correct number', value=acn, format='%.1f')
        additional_correct_number.style('font-size: medium;')

        target_power = ui.number(label='target power', value=40.0)
        target_power.style('font-size: medium;')

        def update_fn():
            cn, acn, cop = get_correct_numbers()
            current_output_power.text = f'current output power: {cop:.3f}'
            correct_number.value = cn
            additional_correct_number.value = acn

        def save_fn():
            ac = AutomaticControlApi()
            ac.set_output_power_correct_number(index, float(correct_number.value))
            ac.set_additional_output_power_correct_number(index, float(additional_correct_number.value))

        calibrate_status = []

        async def calibrate_fn():
            ac = AutomaticControlApi()
            control_api = ControlApi()

            block_type = control_api.get_control_state('block_state')

            powers = [0.0] * 6
            cable_loss = [0.0] * 6
            states = [False] * 6

            powers[index] = float(target_power.value)
            states[index] = True
            if index == 1:
                control_api.set_control_state('block_state', True)

            for e in calibrate_status:
                e.visible = False

            calibrate_status[-1].visible = True
            await asyncio.sleep(0.1)

            try:
                status = ac.calibrate(
                    powers[2:6], cable_loss[2:6], states[2:6],
                    powers[0:2], cable_loss[0:2], states[0:2],
                    False, 0 <= index <= 1, 2 <= index <= 5
                )

                calibrate_status[-1].visible = False
                calibrate_status[int(status)].visible = True
            except Exception:
                calibrate_status[0].visible = True

            if index == 1:
                control_api.set_control_state('block_state', block_type, True)

        with ui.row():
            update = ui.button("Save", on_click=save_fn)
            save = ui.button("Update", on_click=update_fn)
            calibrate = ui.button("Calibrate", on_click=calibrate_fn)

            calibrate_status.append(ui.icon('highlight_off', size='lg', color='#C0392B'))
            calibrate_status.append(ui.icon('check_circle_outline', size='lg', color='#2ECC71'))
            calibrate_status.append(ui.icon('report_problem', size='lg', color='#F1C40F'))
            calibrate_status.append(ui.spinner('gears', size='lg'))
            calibrate_status[0].style('color: #C0392B')
            calibrate_status[1].style('color: #2ECC71')
            calibrate_status[2].style('color: #F1C40F')
            for e in calibrate_status:
                e.visible = False

            calibrate_status[2].visible = True


with ui.row():
    create_card('RM1', '#BA4A00')
    create_card('RM2', '#BA4A00')

with ui.row():
    create_card('SM1', '#D68910')
    create_card('SM2', '#D68910')
    create_card('SM3', '#D68910')
    create_card('SM4', '#D68910')


ui.run(port=8806, title='debug', loop="asyncio", reload=False)
